home *** CD-ROM | disk | FTP | other *** search
/ The Programmer Disk / The Programmer Disk (Microforum).iso / xpro / c4 / pro13 / header.c < prev    next >
C/C++ Source or Header  |  1991-02-13  |  9KB  |  393 lines

  1. /***********************************************************
  2.     header.c -- handle headers
  3. ***********************************************************/
  4. #define MSDOS
  5. #define MYDOS 'M'
  6.  
  7. #include <stdio.h>
  8. #include <io.h>
  9. #include <dos.h>
  10. #include <time.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include "lh.h"
  14. #include "intrface.h"
  15. #include "errmes.h"
  16.  
  17. #define HDRwork      (uchar *)(work +  0)
  18. #define HDRsize      (uchar *)(work +  0)
  19. #define HDRwhole     (uchar *)(work +  0)
  20. #define HDRsum       (uchar *)(work +  1)
  21. #define HDRmethod    (uchar *)(work +  2)
  22. #define HDRpacked    (uchar *)(work +  7)
  23. #define HDRoriginal  (uchar *)(work + 11)
  24. #define HDRtime      (uchar *)(work + 15)
  25. #define HDRattr      (uchar *)(work + 19)
  26. #define HDRlevel     (uchar *)(work + 20)
  27. #define HDRfnlen     (uchar *)(work + 21)
  28. #define HDRfname     (uchar *)(work + 22)
  29. #define HDRdos       (uchar *)(work + 23)
  30. #define HDRextsize   (uchar *)(work + 24)
  31.  
  32. struct head hpb;
  33.  
  34. char methodID[6] = "\0\0\0\0\0\0";
  35.  
  36. static ulong  nextpos;
  37.  
  38. #ifdef MSDOS
  39.     #define Convint(p) (*(int *)(p))
  40.     #define Convlong(p) (*(long *)(p))
  41. #else
  42.     #define Convint(p) (*(p) + ((unsigned)*((p) + 1) << 8))
  43.     #define Convlong(p) (Convint(p) + ((ulong)Convint((p) + 2) << 16))
  44. #endif
  45.  
  46. #ifdef MSDOS
  47.     #define Setint(p, q) (*(uint *)(p)=q)
  48.     #define Setlong(p, q) (*(ulong *)(p)=q)
  49. #else
  50.     #define Setint(p, q) {uint a = q; (p)[0] = a; (p)[1] = a >> 8;}
  51.     #define Setlong(p, q) {ulong a = q; \
  52.                             (p)[0] = a; (p)[1] = a >> 8; \
  53.                             (p)[2] = a >> 16; (p)[3] = a >> 24;}
  54.     #define MAXNAMELEN 128
  55. #endif
  56.  
  57. ulong inithdr(void)
  58. {
  59.     long pos;
  60.     int c, err;
  61.     char *p;
  62.  
  63.     pos = 0;
  64.     while ((c = getc(file1)) >= 0) {
  65.         pos++;
  66.         if (c == '-') {
  67.             getc(file1); getc(file1); getc(file1);
  68.             if (getc(file1) == '-') {
  69.                 nextpos = pos - 3;
  70.                 p = gethdr(&err);
  71.                 if (p) {
  72.                     free(p);
  73.                     nextpos = pos - 3;
  74.                     return nextpos;
  75.                 }
  76.             }
  77.             fseek(file1, pos, SEEK_SET);
  78.         }
  79.     }
  80.     nextpos = pos;
  81.     return nextpos;
  82. }
  83.  
  84. /*******************************
  85.   calculate check-sum of header
  86. *******************************/
  87. static char calcsum(void *h)
  88. {
  89.     char *p, *q, i;
  90.  
  91.     p = (char *)h + 2;
  92.     q = p + *(uchar *)h;
  93.     for (i = 0; p < q; p++)
  94.         i += *p;
  95.     return i;
  96. }
  97.  
  98. static void extheader(char *exthdr, int size)
  99. {
  100.     uchar *p;
  101.  
  102.     p = exthdr + 1;
  103.     switch (*exthdr) {
  104.     case 0:
  105.         hpb.headcrc = Convint(p);
  106.         hpb.crcpos = p;
  107.         if (size > 5)
  108.             hpb.info = *(p + 2);
  109.         break;
  110.     case 1:
  111.         hpb.filename = p;
  112.         hpb.filenlen = size - 3;
  113.         break;
  114.     case 2:
  115.         hpb.pathname = p;
  116.         hpb.dirnlen = size - 3;
  117.         break;
  118.     case 0x40:
  119.         if (hpb.dos == MYDOS) {
  120.             hpb.attr = Convint(p);
  121.         }
  122.         break;
  123.     }
  124. }
  125.  
  126.  
  127. #define readarc(a,b) fread(a, 1, b, file1)
  128.  
  129. char *gethdr(int *err)
  130. /***
  131.   *err = 0 : normal end of header
  132.        = 1 : not a header
  133. ****/
  134. {
  135.     char *p;
  136.     int namelen, extsize;
  137.     int i;
  138.  
  139.     *err = 0;
  140.     hpb.crcpos = NULL;
  141.     *HDRsize = *HDRlevel = 0;
  142.     fseek(file1, nextpos, SEEK_SET);
  143.     if (readarc(HDRwork, 21) != 21 || *HDRsize == 0) return NULL;
  144.     hpb.headersize = (int)*HDRsize + 2;
  145.     strncpy(hpb.method, HDRmethod, 5);
  146.     hpb.packed = hpb.skip = Convlong(HDRpacked);
  147.     hpb.original = Convlong(HDRoriginal);
  148.     hpb.level = *HDRlevel;
  149.     hpb.attr = *HDRattr;
  150.     hpb.dirnlen = 0;
  151.     switch(hpb.level) {
  152.     case 0:
  153.     case 1:
  154.         hpb.dostime.u = Convlong(HDRtime);
  155.         hpb.utc = dos2unix(&hpb.dostime.s);
  156.         if (hpb.headersize < 22) return NULL;
  157.         readarc(HDRwork + 21, hpb.headersize - 21);
  158.         if (calcsum(HDRwork) != *HDRsum) {
  159.             if (*HDRwork == 0x1a) return NULL;    /* for LArc & XMODEM */
  160.             *err = 1;
  161.             return NULL;
  162.         }
  163.         namelen = *HDRfnlen;
  164.         hpb.filenlen = namelen;
  165.         hpb.filename = hpb.pathname = HDRfname;
  166.         i = hpb.headersize - namelen;
  167.         if (i >= 24) {
  168.             hpb.filecrc = Convint(HDRfname + namelen);
  169.         } else {
  170.             hpb.level = -1;
  171.         }
  172.         if (i >= 25) {
  173.             hpb.dos = *(HDRfname + namelen + 2);
  174.         }
  175.         nextpos = ftell(file1) + hpb.skip;
  176.         if (hpb.level <= 0) {
  177.             strncpy(hpb.pathname = e_malloc(namelen + 1), HDRfname, namelen);
  178.             hpb.pathname[namelen] = '\0';
  179.             hpb.filename = convdelim(hpb.pathname, DELIM);
  180.             return hpb.pathname;
  181.         }
  182.         p = HDRwork + *HDRsize;
  183.         while ((extsize = Convint(p)) != 0) {
  184.             readarc(p + 2, extsize);
  185.             extheader(p + 2, extsize);
  186.             p += extsize;
  187.         }
  188.         i = p + 2 - HDRwork;
  189.         hpb.packed -= i - hpb.headersize;
  190.         hpb.headersize = i;
  191.         break;
  192.     case 2:
  193.         readarc(HDRwork + 21, (hpb.headersize = Convint(HDRwhole)) - 21);
  194.         hpb.utc = Convlong(HDRtime);
  195.         hpb.dos = *HDRdos;
  196.         p = HDRextsize;
  197.         while ((extsize = Convint(p)) != 0) {
  198.             extheader(p + 2, extsize);
  199.             p += extsize;
  200.         }
  201.         hpb.filecrc = Convint(HDRfnlen);
  202.         nextpos = ftell(file1) + hpb.skip;
  203.         if (hpb.crcpos == NULL) {
  204.             *err = 1;
  205.             return NULL;
  206.         }
  207.         break;
  208.     default:
  209.         if (*HDRsize != 0x1a) *err = 1;
  210.         return NULL;
  211.     }
  212.     if (hpb.crcpos) {
  213.         Setint(hpb.crcpos, 0);
  214.         crc = 0;
  215.         if (calccrc(HDRwork, hpb.headersize) != hpb.headcrc) {
  216.             *err = 1;
  217.             return NULL;
  218.         }
  219.         Setint(hpb.crcpos, hpb.headcrc);
  220.     }
  221.     namelen = hpb.dirnlen + hpb.filenlen;
  222.     p = e_malloc(namelen + 1);
  223.     hpb.pathname = strncpy(p, hpb.pathname, hpb.dirnlen);
  224.     hpb.filename = strncpy(p + hpb.dirnlen, hpb.filename, hpb.filenlen);
  225.     *(p + namelen) = '\0';
  226.     convdelim(hpb.pathname, DELIM);
  227.     return hpb.pathname;
  228. }
  229.  
  230. void makehdr(void)
  231. {
  232.     int namelen;
  233.     uchar *p, *q;
  234.  
  235.     hpb.crcpos = NULL;
  236.     memcpy(HDRmethod, hpb.method, 5);
  237.     Setlong(HDRpacked, hpb.skip = hpb.packed);
  238.     Setlong(HDRoriginal, hpb.original);
  239.     *HDRattr = 0x20;
  240.     *HDRlevel = hpb.level;
  241.     q = hpb.filename;
  242.     if (hpb.level == 0) q = hpb.pathname;
  243.     namelen = strlen(q);
  244.     p = HDRfnlen;
  245.     if (hpb.level != 2) {
  246. #ifndef MSDOS
  247.         if (namelen > MAXNAMELEN) {
  248.             *p++ = 0;
  249.         } else
  250. #endif
  251.         {
  252.             *p++ = namelen;
  253.             strcpy(p, q);
  254.             if (hpb.level == 0) convdelim(p, pathdelim);
  255.             p += namelen;
  256.         }
  257.         hpb.dostime.s = *unix2dos(hpb.utc);
  258.         Setlong(HDRtime, hpb.dostime.u);
  259.     } else {
  260.         Setlong(HDRtime, hpb.utc);
  261.     }
  262.  
  263.     Setint(p, hpb.filecrc); /* filecrc (for SFX) */
  264.     p += 2;
  265.     if (hpb.level == 0) {
  266.         *HDRsize = p - HDRmethod;
  267.         hpb.headersize = p - HDRwork;
  268.         *HDRattr = hpb.attr;
  269.         *HDRsum = calcsum(HDRwork);
  270.         return;
  271.     }
  272.     *p = MYDOS; p++;
  273.     *HDRsize = p - HDRwork;
  274.  
  275. /*
  276. |  filename header     |
  277. |   2 ext-header size  |
  278. |----------------------|
  279. |   1 0x01             |
  280. |   ? filename         |
  281. |----------------------|
  282. */
  283.     if (hpb.level == 2
  284. #ifndef MSDOS
  285.     || namelen > MAXNAMELEN
  286. #endif
  287.     ) {
  288.         hpb.filenlen = strlen(hpb.filename);
  289.         Setint(p, hpb.filenlen + 3); p += 2;
  290.         *p++ = 1;
  291.         memcpy(p, hpb.filename, hpb.filenlen); p += hpb.filenlen;
  292.     }
  293.  
  294. /*
  295. |  dirname header      |
  296. |   2 ext-header size  |
  297. |----------------------|
  298. |   1 0x02             |
  299. |   ? dirname          |
  300. |----------------------|
  301. */
  302.     if (hpb.pathname != hpb.filename) {
  303.         hpb.dirnlen = hpb.filename - hpb.pathname;
  304.         Setint(p, hpb.dirnlen + 3); p += 2;
  305.         *p++ = 2;
  306.         convdelim(hpb.pathname, DELIM2);
  307.         memcpy(p, hpb.pathname, hpb.dirnlen); p += hpb.dirnlen;
  308.         convdelim(hpb.pathname, DELIM);
  309.     }
  310.  
  311. #ifdef MSDOS
  312. /*
  313. |  attribute header    |
  314. |   2 ext-header size  |
  315. |----------------------|
  316. |   1 0x40             |
  317. |   2 attribute        |
  318. |----------------------|
  319. */
  320.     if (hpb.attr != 0x20) {
  321.         Setint(p, 5); p += 2;
  322.         *p++ = 0x40;            /* ext-header type */
  323.         Setint(p, hpb.attr); p += 2;
  324.     }
  325. #endif
  326.  
  327. /*
  328. |  common header       |
  329. |   2 ext-header size  |
  330. |----------------------|
  331. |   1 0x00             |
  332. |   2 header crc       |
  333. | ( 1 information )    |
  334. |----------------------|
  335. */
  336.     if (p != HDRwork + *HDRsize || hpb.info) {
  337.         q = p; p += 2;
  338.         *p++ = 0;                    /* ext-header type */
  339.         hpb.crcpos = p;
  340.         Setint(p, 0); p += 2;        /* dummy crc */
  341.         if (hpb.info) {
  342.             *p++ = hpb.info;
  343.         }
  344.         Setint(q, p - q);
  345.     }
  346.  
  347. /*  ext-header end  */
  348.     Setint(p, 0); p += 2;
  349.  
  350.     hpb.headersize = p - HDRwork;
  351.     if (hpb.level == 2) {
  352.         if ((hpb.headersize & 0xff) == 0) {
  353.             hpb.headersize++;
  354.             *p = '\0';
  355.         }
  356.         Setint(HDRsize, hpb.headersize);
  357.     }
  358. }
  359.  
  360. void writehdr(void)
  361. {
  362.     hpb.currentpos = ftell(file2);
  363.     if (fwrite(HDRwork, hpb.headersize, 1, file2) == 0)
  364.         error(WTERR, filename2);
  365. }
  366.  
  367. void adjusthdr(void)
  368. {
  369.     long lastpos;
  370.     uchar *p;
  371.  
  372.     lastpos = ftell(file2);
  373.     fseek(file2, hpb.currentpos, SEEK_SET);
  374.     if (hpb.level == 1) {
  375.         hpb.skip = hpb.headersize - *HDRsize - 2 + hpb.packed;
  376.         Setlong(HDRpacked, hpb.skip);
  377.     } else {
  378.         Setlong(HDRpacked, hpb.packed);
  379.     }
  380.     p = HDRfnlen;
  381.     if (hpb.level != 2) p += *p + 1;
  382.     Setint(p, hpb.filecrc);
  383.     memcpy(HDRmethod, hpb.method, 5);
  384.     if (hpb.level != 2) *HDRsum = calcsum(HDRwork);
  385.     if (hpb.crcpos) {
  386.         crc = 0;
  387.         Setint(hpb.crcpos, 0);
  388.         Setint(hpb.crcpos, calccrc(HDRwork, hpb.headersize));
  389.     }
  390.     fwrite(HDRwork, hpb.headersize, 1, file2);
  391.     fseek(file2, lastpos, SEEK_SET);
  392. }
  393.